François Goffinet linux.goffinet.org 64-82 minutes
•.KVM Virtualization in RHEL 7 Made Easy, A Dell Technical White Paper, September 2014.
•.RHEL7 Virtualization deployment and administration guide, 2015.
On trouvera sur le dépot GIT https://github.com/goffinet/virt-scripts des scripts utiles à ce chapitre.
apt-get update && apt-get upgrade -y && apt-get install git -y
cd ~
git clone https://github.com/goffinet/virt-scripts
cd virt-scripts
1.Concepts virtualisation KVM
•.Installer KVM et ses outils de gestion
•.Créer une VM avec virt-manager
•.Administration avec virsh
•.Créer un dépôt local HTTP
•.Créer des VMs avec virt-install
•.Automatiser une l’installation avec kickstart
•.Accéder à la console (graphique te texte) et la dépanner
•.Machine virtuelle, domaine invité sont des ordinateurs dont le matériel est reproduit de manière logicielle sur l’hôte de virtualisation.
•.L’hôte de virtualisation, machine physique a priori, embarque le logiciel hyperviseur qui interprète les pilotes de périphériques virtuels et offrent l’accès au processeur (CPU) et à la mémoire de travail (vive, RAM).
•.Pour un déploiement en production, il est préférable d’équiper une infrastructure d’au moins deux hyperviseurs, un réseau de production, un réseau de gestion et un réseau de stockage avec un SAN défié en iSCSI.
•.Pour une solution de Lab, un PoC, un projet personnel, il est préférable d’exécuter toutes fonctions sur un seul ordinateur quitte à passer à la Nested Virtualization.
•.Nested Virtualization : La capacité de virtualiser un hypeviseur : KVM dans KVM, Hyper-V dans Hyper-V, VMWare ESXi dans ESXi, etc. Il est nécessaire d’activer les instructions “Intel VT-x or AMD-V” (32 bits) et Intel EPT or AMD RVI (64 bits).
•.Isolateur : Docker, LXC, OpenVZ, BSD Jails
•.Noyau en espace utilisateur
•.Hyperviseur de type 2 / type 1
•.Virtualisation totale (Full virtualization) : qemu
•.Virtualisation Hardware-Assisted : qemu+KVM
•.Paravirtualisation : qemu+KVM+virtio, Xen
KVM est un hyperviseur de type 1 qui s’utilise aussi bien dans :
•.des environnements de développement, de test, d’apprentissage
•.la virtualisation de centres de données (data center)
•.la mise en place d’infrastructures en nuage (cloud)
Sur le plan technique, en général et particulièrement avec KVM, une machine virtuelle (VM) est représentée par :
1.un fichier de définition qui reprend les caractéristiques de la machine, par défaut situé (en format XML) dans /etc/libvirt/qemu/.
2.un ou des fichier(s) qui représentent les disques par défaut placés dans /var/lib/libvirt/images/.
Les principales ressources de virtualisation sont :
•.La puissance (CPU/RAM)
•.Le stockage (disques)
•.Le réseau
Mais pour fonctionner, une VM a aussi besoin de bien d’autres interfaces matérielles qui peuvent être émulées ou para-virtualisées.
KVM Kernel-based Virtual Machine :
•.KVM est le module qui transforme le noyau Linux en Hyperviseur type 1 (HVM et PV avec virtio). Ce module traduit rapidement les instructions des vCPU via les intructions VT AMD et Intel. Il prend aussi en charge des aspects de bas niveau de l’architecture x86.
•.KVM est aussi un émulateur de matériel qui utilise qemu et les pilotes virtio.
Vue du noyau :
•.Chaque VM est un processus
•.Chaque vCPU est un thread de processeur.
Features :
•.CPU and memory overcommit
•.High performance paravirtual I/O
•.Hotplug (cpu, block, nic)
•.SMP guests
•.Live Migration Power management
•.PCI Device Assignment and SR-IOV
•.KSM (Kernel Samepage Merging)
•.SPICE, VNC, text
•.NUMA
Qemu est un émulateur de diverses architectures dont x86 (Hyperviseur de type 2). Combiné au pilote KVM, il permet de réaliser de l’accélération Hardware (HVM).
L’outil de base qemu-img permet de créer et de gérer des images disque.
En format local les images disques peuvent se trouver en formats :
•.raw
•.qcow2
Par ailleurs, on peut utiliser directement des volumes logiques LVM.
libvirt un API de virtualisation Open Source qui s’interface avec un hyperviseur pour administrer les VMs.
•.virsh : cli pour libvirt
•.qemu-img : permet de gérer les images des disques
•.virt-manager : client graphique
•.virt-install : commande pour la création des machines virtuelles
•.virt-viewer : client console graphique (spice)
•.virt-clone : outil de clonage
•.virt-top : top de VM libvirt
libguestfs est un ensemble d’outils qui permettent d’accéder aux disques des machines virtuelles et de les modifier.
Ces outils permettent de :
•.d’accéder et de modifier un système de fichier invité à partir de l’hôte
•.virt-builder permet de créer des VM à partir d’un dépôt d’images
•.virt-syspreppermet de “préparer” une VM à cloner
•.d’obtenir des informations complètes dur l’usage des disques
•.de convertir des machines en P2V ou V2V
•.…
Périphérique réseau virtio.
•.Kimchi est un outil de gestion en HTLM5 pour KVM basé sur libvirt. Il s’agit d’une solution à hôte unique.
•.oVirt est aussi une plateforme Web de gestion de virtualisation multi-hôtes supportant d’autres hyperviseur, des volumes NFS, iSCSI ou FC (Fiber Channel), surveillance, fine tuning des ressources.
Les instructions VT doivent être activées dans le Bios (Netsted Virtualization) :
grep -E 'svm|vmx' /proc/cpuinfo
•.vmx : processeurs Intel
•.svm : processeurs AMD
ou encore
lscpu | grep Virtualisation
Mise à jour du sytème et installation des paquets KVM :
En RHEL7/Centos7.
yum update -y
yum group install "Virtualization Host" "Virtualization Client"
yum -y install \
qemu-kvm \
dejavu-lgc-sans-fonts \
libguestfs-tools
Démarrer le service libvirtd :
systemctl enable libvirtd && systemctl start libvirtd
Démarrer le service chronyd :
# systemctl enable chronyd && systemctl start chronyd
En Debian 8.
apt-get update && sudo apt-get -y upgrade
apt-get -y install qemu-kvm libvirt-bin virtinst virt-viewer libguestfs-tools virt-manager uuid-runtime
Démarrage du commutateur virtuel par défaut.
virsh net-start default
virsh net-autostart default
Vérification du chargement du module kvm.
Libvirt propose un outil de vérification de l’hôte.
virt-host-validate
QEMU: Vérification for hardware virtualization : PASS
QEMU: Vérification for device /dev/kvm : PASS
QEMU: Vérification for device /dev/vhost-net : PASS
QEMU: Vérification for device /dev/net/tun : PASS
LXC: Vérification pour Linux >= 2.6.26 : PASS
Vérification du démarrage de libvirt :
systemctl status libvirtd
Configuration du réseau par défaut :
Une interface bridge virbr0 192.168.122.1 est “natée” à l’interface physique. Le démon dnsmasq fournit le service DNS/DHCP.
ip add sh virbr0
ip route
iptables -t nat -L -n -v
cat /proc/sys/net/ipv4/ip_forward
L’emplacement par défaut de l’espace de stockage des disques est /var/lib/libvirt/images/. La définition des machines virtuelles est située dans /etc/libvirt/qemu/.
Il est peut-être plus aisé de désactiver pour l’instant firewalld (systemctl stop firewalld).
On propose ici un script de préparation de l’hôte de virtualisation :
https://raw.githubusercontent.com/goffinet/virt-scripts/master/autoprep.sh
Virt-manager est un outil graphique de gestion des hyperviseurs connecté via libvirt.
Dans une session X Window, suivre Quick Start with virt-manager ou encore KVM, Qemu, libvirt en images.
A ajouter : images à exécuter
Avec libvirt et KVM, une “Machine Virtuelle (VM)” est appelée un “Domaine”.
Démarrage d’un domaine :
Arrêt d’un domaine :
Extinction d’un domaine (comme on retire une prise de courant, il ne s’agit pas d’effacer le domaine) :
Pour retirer une VM (le ou les disques associés persistent) :
Pour retirer un domaine (et en effaçant ses disques) :
virsh undefine vm1 --remove-all-storage
Redémarrage d’un domaine :
Informations détaillées :
Liste des domaines :
Démarrage du domaine au démarrage de l’hôte :
Désactiver l’activation au démarrage :
virsh autostart vm1 --disable
Accéder à la console série (texte) du domaine :
Accéder à la console graphique du domaine :
La commande qui permet de créer une machine virtuelle et de la lancer (pour y installer un système d’exploitation) est virt-install. Cette commande peut comporter un certain nombre de paramètres. Il est plus intéressant de travailler avec des scripts.
Dans le but de cloner un domaine existant, on s’intéressa à ce qui constitue fondamentalement une machine virtuelle :
•.un fichier de définition de VM écrit en XML
•.et un disque virtuel.
Les procédures de création ou de mise à jour d’objet (réseau, volume, domaine) avec la commande virsh consiste à manipuler des définitions XML :
•.define / undefine
•.destroy /start /autostart
On peut créer une machine virtuelle lancer une installation à partir du shell avec virt-install et des options.
Création et lancement d’une VM :
•.RAM 1024/1 vCPU
•.HD 8Go (raw)
•.ttyS0
•.console vnc
•.Installation CD-ROM
#!/bin/bash
# vm-install1.sh
# local path to the iso
iso=/var/lib/iso/CentOS-7-x86_64-DVD-1611.iso
# Stop and undefine the VM
/bin/virsh destroy $1; /bin/virsh undefine $1 --remove-all-storage
# graphical console
# via local ISO
virt-install \
--virt-type kvm \
--name=$1 \
--disk path=/var/lib/libvirt/images/$1.img,size=8 \
--ram=1024 \
--vcpus=1 \
--os-variant=rhel7 \
--graphics vnc \
--console pty,target_type=serial \
--cdrom $iso
Avant de procéder à un export, il est préférable de suspendre la VM d’origine :
On peut rediriger un “dump” de la VM d’origine dans un fichier xml.
virsh dumpxml vm1 > vm2.xml
Ensuite, il faut adapter ce fichier en retirant la valeur id et le champ uuid en modifiant le champ name, la balise source file qui désigne l’emplacement du nouveau disque, le champ mac address et en supprimant des balises entre </devices> et </domain>.
Le second élément nécessaire à l’exécution de la VM est un disque dédié, soit la copie du disque de la machine originale :
cp /var/lib/libvirt/images/vm1.img /var/lib/libvirt/images/vm2.img
Enfin, on peut intégrer la machine à libvirtet la démarrer :
virsh define vm2.xml
virsh start vm2
A lire attentivement, voici le fichier vm2.xml adapté (uuid, devices, disks, mac):
<domain type='kvm'>
<name>vm2</name>
<memory unit='KiB'>1048576</memory>
<currentMemory unit='KiB'>1048576</currentMemory>
<vcpu placement='static'>1</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<cpu mode='custom' match='exact'>
<model fallback='allow'>Westmere</model>
</cpu>
<clock offset='utc'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/vm2.img'/>
<backingStore/>
<target dev='vda' bus='virtio'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</disk>
<controller type='usb' index='0' model='ich9-ehci1'>
<alias name='usb0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x7'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci1'>
<alias name='usb0'/>
<master startport='0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' multifunction='on'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci2'>
<alias name='usb0'/>
<master startport='2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci3'>
<alias name='usb0'/>
<master startport='4'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'>
<alias name='pci.0'/>
</controller>
<interface type='bridge'>
<mac address='52:54:00:8a:c3:2a'/>
<source bridge='virbr0'/>
<target dev='vnet0'/>
<model type='virtio'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<serial type='pty'>
<source path='/dev/pts/0'/>
<target type='isa-serial' port='0'/>
<alias name='serial0'/>
</serial>
<console type='pty' tty='/dev/pts/0'>
<source path='/dev/pts/0'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<input type='tablet' bus='usb'>
<alias name='input0'/>
</input>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</memballoon>
</devices>
</domain>
L’utilitaire virt-clone permet de cloner (à l’identique) une VM. virt-cloneprend la peine de générer une nouvelle adresse MAC et un nouvel uuid pour le domaine. Il s’occupe également de dupliquer le ou les disques attachés au domaine.
Imaginons que l’on veuille cloner proprement la machine vm1 en machine vm2 dans le but de :
•.générer une copie de sauvegarde de toute la machine
•.générer une copie de sauvegarde de base de donnée afin de travailler sur une base de donnée hébergée. Dans ce cas, il est peut être intéressant de connecter le clone sur un réseau isolé du réseau de production.
•.dupliquer un même modèle
Attention, il faudra malgré tout modifier le fichier de configuration du réseau en retirant l’adresse mac et l’uuid dans le système d’exploitation invité. (/etc/sysconfig/network-scripts/ifcfg-*) si on désire exécuter le domaine original et son clone sur le même réseau ou si l’adresse IP est fixe.
Avant tout, vérifions l’état de la machine. Mettons-la en suspension pour assurer une copie correcte des disques :
virsh list
ID Nom État
----------------------------------------------------
73 vm1 en cours d'exécution
virsh suspend vm1
Domaine vm1 suspendu
virsh list
ID Nom État
----------------------------------------------------
73 vm1 mis en pause
Procédons au clonage :
virt-clone \
--original vm1 \
--name vm2 \
--file /var/lib/libvirt/images/vm2.img
virsh list --all
ID Nom État
----------------------------------------------------
73 vm1 mis en pause
- vm2 fermé
Reprise de la machine :
virsh resume vm1
Domaine vm1 réactivé
Pour la transformation d’une machine virtuelle en modèle (template), on peut utiliser virt-sysprep qui vient avec libguestfs, avant le clonage pour remettre à zéro ses propriétés.
# virt-sysprep --list-operations
abrt-data * Remove the crash data generated by ABRT
bash-history * Remove the bash history in the guest
blkid-tab * Remove blkid tab in the guest
ca-certificates Remove CA certificates in the guest
crash-data * Remove the crash data generated by kexec-tools
cron-spool * Remove user at-jobs and cron-jobs
customize * Customize the guest
dhcp-client-state * Remove DHCP client leases
dhcp-server-state * Remove DHCP server leases
dovecot-data * Remove Dovecot (mail server) data
firewall-rules Remove the firewall rules
flag-reconfiguration Flag the system for reconfiguration
fs-uuids Change filesystem UUIDs
kerberos-data Remove Kerberos data in the guest
logfiles * Remove many log files from the guest
lvm-uuids * Change LVM2 PV and VG UUIDs
machine-id * Remove the local machine ID
mail-spool * Remove email from the local mail spool directory
net-hostname * Remove HOSTNAME in network interface configuration
net-hwaddr * Remove HWADDR (hard-coded MAC address) configuration
pacct-log * Remove the process accounting log files
package-manager-cache * Remove package manager cache
pam-data * Remove the PAM data in the guest
puppet-data-log * Remove the data and log files of puppet
rh-subscription-manager * Remove the RH subscription manager files
rhn-systemid * Remove the RHN system ID
rpm-db * Remove host-specific RPM database files
samba-db-log * Remove the database and log files of Samba
script * Run arbitrary scripts against the guest
smolt-uuid * Remove the Smolt hardware UUID
ssh-hostkeys * Remove the SSH host keys in the guest
ssh-userdir * Remove ".ssh" directories in the guest
sssd-db-log * Remove the database and log files of sssd
tmp-files * Remove temporary files
udev-persistent-net * Remove udev persistent net rules
user-account Remove the user accounts in the guest
utmp * Remove the utmp file
yum-uuid * Remove the yum UUID
Les sources d’installation doivent contenir au minimum ceci :
{product path}
|
+--base
|
+--RPMS
product path :
•.RedHat
•.Fedora
•.Centos
base : metadonnées
RPMS : Fichiers Red Hat Package Manager
Installer Apache :
yum -y install httpd
systemctl enable httpd.service && systemctl start httpd.service
Télécharger une image
mkdir -p /var/lib/iso
cd /var/lib/iso
wget https://centos.mirrors.ovh.net/ftp.centos.org/7/isos/x86_64/CentOS-7-x86_64-DVD-1611.iso
Monter l’ISO :
mount -o loop,ro CentOS*.iso /mnt
Copier les fichiers
mkdir /var/www/html/repo/
cp -rp /mnt/* /var/www/html/repo/
chcon -R -t httpd_sys_content_t /var/www/html
Monter l’ISO directement dans /var/www/html/repo/ est une alternative.
Création et lancement d’une VM :
•.RAM 1024/1 vCPU
•.HD 8Go (raw)
•.ttyS0
•.console vnc
•.Installation repo HTTP local ou distant
#!/bin/bash
# vm-install2.sh
# KVM Host IP
bridge=192.168.122.1
# Repo URL
mirror=https://$bridge/repo
#mirror=https://centos.mirrors.ovh.net/ftp.centos.org/7/os/x86_64
#mirror=https://ftp.belnet.be/ftp.centos.org/7/os/x86_64
#mirror=https://mirror.i3d.net/pub/centos/7/os/x86_64
# Stop and undefine the VM
/bin/virsh destroy $1; /bin/virsh undefine $1 --remove-all-storage
# graphical console, bridged
# via http repo
virt-install \
--virt-type kvm \
--name=$1 \
--disk path=/var/lib/libvirt/images/$1.img,size=8 \
--ram=1024 \
--vcpus=1 \
--os-variant=rhel7 \
--network bridge=virbr0 \
--graphics vnc \
--console pty,target_type=serial \
--location $mirror
Kickstart permet d’automatiser les installations RHEL/Fedora/Centos (et d’autres) en indiquant un fichier de configuration qui est lu avant le logiciel d’installation Anaconda.
•.On rend le fichier kickstart disponible via HTTP (local, NFS, FTP) dans un dans dossier conf
mkdir /var/www/html/conf/
touch vm.ks /var/www/html/conf/
chcon -R -t httpd_sys_content_t /var/www/html
•.Il est appelé par virt-install (directement au lancement du noyau)
Ce fichier de configuration est rédigé :
•.Automatiquement par Anaconda sur toute installation RHEL/Centos/Fedora :
less /root/anaconda-ks.cfg
•.On peut le générer en l’éditant via le programme :
yum install system-config-kickstart
system-config-kickstart
Voici la configuration d’une installation simple avec un fichier /var/www/html/conf/vm.ks :
•.Clavier local, horodatage, réseau dhcp, nom, mot de passe, Swap, /boot, LVM, @core, chrony
# File /var/www/html/conf/vm.ks
keyboard --vckeymap=be-oss --xlayouts='be (oss)'
lang fr_BE.UTF-8
network --onboot=on --bootproto=dhcp --device=link --hostname=localhost.localdomain
rootpw testtest
services --enabled="chronyd"
timezone Europe/Paris --isUtc
bootloader --location=mbr --boot-drive=vda
clearpart --all --initlabel --drives=vda
ignoredisk --only-use=vda
part pv.0 --fstype="lvmpv" --ondisk=vda --size=5000
part /boot --fstype="xfs" --ondisk=vda --size=500
volgroup vg0 --pesize=4096 pv.0
logvol swap --fstype="swap" --size=500 --name=swap --vgname=vg0
logvol / --fstype="xfs" --size=3072 --name=root --vgname=vg0
%packages --ignoremissing
@core
chrony
%end
reboot
Avec la machine virtuelle :
•.RAM 1024/1 vCPU
•.HD 8Go (qcow2)
•.ttyS0
•.console vnc
•.Installation repo HTTP local ou distant
#!/bin/bash
# vm-install3.sh
bridge=192.168.122.1
mirror=https://$bridge/repo
#mirror=https://centos.mirrors.ovh.net/ftp.centos.org/7/os/x86_64
#mirror=https://ftp.belnet.be/ftp.centos.org/7/os/x86_64
#mirror=https://mirror.i3d.net/pub/centos/7/os/x86_64
#Stop and undefine the VM
/bin/virsh destroy $1; /bin/virsh undefine $1 --remove-all-storage
# Graphical console, bridged, HD qcow2
# HTTP + Kickstart
virt-install \
--virt-type kvm \
--name=$1 \
--disk path=/var/lib/libvirt/images/$1.qcow2,size=16,format=qcow2 \
--ram=1024 \
--vcpus=1 \
--os-variant=rhel7 \
--network bridge=virbr0 \
--graphics vnc \
--console pty,target_type=serial \
--location $mirror \
-x ks=https://$bridge/conf/vm.ks
Voici la configuration d’une installation simple en console texte avec un fichier /var/www/html/conf/vm2.ksrevu par system-config-kickstart :
•.Clavier local, horodatage, réseau dhcp, nom, firewall désactivé, selinux désactivé, pas de serveur X, console texte, mot de passe, Swap, /boot, LVM, @core, chrony
# File /var/www/html/conf/vm2.ks
#platform=x86, AMD64, ou Intel EM64T
#version=DEVEL
# Install OS instead of upgrade
install
# Keyboard layouts
# old format: keyboard be-latin1
# new format:
keyboard --vckeymap=be-oss --xlayouts='be (oss)'
# Reboot after installation
reboot
# Root password
rootpw --plaintext testtest
# System timezone
timezone Europe/Paris
# System language
lang fr_BE
# Firewall configuration
firewall --disabled
# Network information
network --bootproto=dhcp --device=link
# System authorization information
auth --useshadow --passalgo=sha512
# Use text mode install
text
# SELinux configuration
selinux --disabled
# Do not configure the X Window System
skipx
# System services
services --enabled="chronyd"
bootloader --location=mbr --boot-drive=vda
clearpart --all --initlabel --drives=vda
ignoredisk --only-use=vda
part pv.0 --fstype="lvmpv" --ondisk=vda --size=5000
part /boot --fstype="xfs" --ondisk=vda --size=500
volgroup vg0 --pesize=4096 pv.0
logvol swap --fstype="swap" --size=500 --name=swap --vgname=vg0
logvol / --fstype="xfs" --size=3072 --name=root --vgname=vg0
%packages --ignoremissing
@core
chrony
%end
Avec la machine virtuelle :
•.RAM 1024/1 vCPU
•.HD 8Go (qcow2)
•.ttyS0
•.console texte
•.Installation repo HTTP local ou distant
#!/bin/bash
# vm-install4.sh
bridge=192.168.122.1
mirror=https://$bridge/repo
#mirror=https://centos.mirrors.ovh.net/ftp.centos.org/7/os/x86_64
#mirror=https://ftp.belnet.be/ftp.centos.org/7/os/x86_64
#mirror=https://mirror.i3d.net/pub/centos/7/os/x86_64
#Stop and undefine the VM
/bin/virsh destroy $1; /bin/virsh undefine $1 --remove-all-storage
# Text console, bridged, HD qcow2
# HTTP + Kickstart
virt-install \
--virt-type kvm \
--name=$1 \
--disk path=/var/lib/libvirt/images/$1.qcow2,size=16,format=qcow2 \
--ram=1024 \
--vcpus=1 \
--os-variant=rhel7 \
--network bridge=virbr0 \
--graphics none \
--console pty,target_type=serial \
--location $mirror \
-x "ks=https://$bridge/conf/vm2.ks console=ttyS0,115200n8 serial"
Pour échapper à la console texte :
CTRL+] (Linux)
CTRL+ALT+* (Mac OS X)
Via une session Xwindows :
ou
ou
netstat -tln|grep :59
vncviewer x.x.x.x:5900
Il faut nécessairement que la machine virtuelle dispose d’une console ttyS0 émulée !
Si la machine n’a pas été configurée avec ce paramètre grub, il faut editer le fichier /etc/default/grub en ajoutant console=ttyS0 ) à la variable GRUB_CMDLINE_LINUX. Le fichier /etc/default/grub devrait ressembler à ceci
# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL="serial console"
GRUB_SERIAL_COMMAND="serial --speed=115200"
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=vg0/root rd.lvm.lv=vg0/swap console=ttyS0,115200n8"
GRUB_DISABLE_RECOVERY="true"
Exécuter :
grub2-mkconfig -o /boot/grub2/grub.cfg
reboot
# virsh console vm1
Connected to domain vm1
Escape character is ^]
CentOS Linux 7 (Core)
Kernel 3.10.0-229.el7.x86_64 on an x86_64
localhost login:
osinfo-query os | grep Microsoft
A condition de disposer d’un ISO de Windows 7, voici un script de configuration d’une VM Windows en mode HVM :
#!/bin/bash
# File vm-install5.sh
#Stop and undefine the VM
/bin/virsh destroy $1; /bin/virsh undefine $1 --remove-all-storage
# Graphical console, bridged, cd-rom
virt-install \
--virt-type kvm \
--name=$1 \
--disk path=/var/lib/libvirt/images/$1.qcow2,size=16,format=qcow2 \
--cdrom /var/win7.iso \
--ram=2048 \
--vcpus=2 \
--arch=x86_64
--os-type=windows \
--os-variant=win7 \
--hvm \
--network bridge=virbr0 \
--keymap=fr \
--sound \
--vnc
On a aussi besoin des pilotes virtio si on utilise la paravirtualisation :
•.Pilote de disque bus=virtio,cache=none; d’autres bus disponibles tels que ‘ide’, ‘sata’, ‘scsi’, ‘usb’.
•.Pilote de carte réseau model=virtio; d’autres options de modèle sont ‘e1000’ ou ‘rtl8139’.
#!/bin/bash
# File vm-install6.sh
...
Voir Wiki sur les pilotes virtio :
wget https://fedorapeople.org/groups/virt/virtio-win/virtio-win.repo -O /etc/yum.repos.d/virtio-win.repo
yum install virtio-win
Où /usr/share/virtio-win/*.iso contient tous les pilotes virtio.
Après l’installation insérer l’iso virtio-tools, mais avant trouver le lecteur cd :
virsh change-media vm3 hdb /usr/share/virtio-win/virtio-win.iso
Pour convertir un disque raw vers qcow2 :
#!/bin/bash
# File raw2qcow2.sh
path=/var/lib/libvirt/images/$1
virsh list
virsh suspend $1
ls -lh $path.img
echo "Conversion du disque"
qemu-img convert -c -O qcow2 $path.img $path.qcow2
mv $path.img $path.old
mv $path.qcow2 $path.img
virsh resume $1
ls -lh $path.*
Pour convertir un disque VB vdi vers raw :
$ VBoxManage clonehd --format RAW WindowsXP.vdi WindowsXP.raw
0%...10%...20%...30%...50%...70%...80%...90%...100%
Clone hard disk created in format 'RAW'. UUID: cfe44508-d957-4c8c-b5c5-2b4f266830d8
…
Import d’une VM via son disque (converti d’une autre solution par exemple) avec virt-install --import --noautoconsole.
#!/bin/bash
## This script import and launch minimal KVM images with a text console ##
## First download all the qcow2 images on https://get.goffinet.org/kvm/ ##
## Usage : bash define-guest.sh <name> <image> ##
## Reset root password with the procedure : ##
## https://linux.goffinet.org/processus_et_demarrage.html#10-password-recovery ##
## Please check all the variables ##
# First parmater as name
name=$1
# Secund parameter image name avaible on "https://get.goffinet.org/kvm/"
# Image name : 'debian7', 'debian8', 'centos7', 'ubuntu1604', 'metasploitable', kali
image="$2.qcow2"
# Generate an unique string
uuid=$(uuidgen -t)
# VCPUs
vcpu="1"
# The new guest disk name
disk="${name}-${uuid:25}.qcow2"
# Diskbus can be 'ide', 'scsi', 'usb', 'virtio' or 'xen'
diskbus="virtio"
size="8"
# Hypervisor can be 'qemu', 'kvm' or 'xen'
hypervisor="kvm"
# RAM in Mb
memory="256"
# Graphics 'none' or 'vnc'
graphics="none"
# Network inetrface and model 'virtio' or 'rtl8139' or 'e1000'
interface="virbr0"
model="virtio"
# Parameters for metasploitable guests
if [ $image = "metasploitable.qcow2" ]; then
diskbus="scsi"
memory="512"
model="e1000"
fi
# Parameters for Kali guests
if [ $image = "kali.qcow2" ]; then
memory="1024"
size="16"
fi
## Local image copy to the default storage pool ##
cp ./$image /var/lib/libvirt/images/$disk
## Import and lauch the new guest ##
virt-install \
--virt-type $hypervisor \
--name=$name \
--disk path=/var/lib/libvirt/images/$disk,size=$size,format=qcow2,bus=$diskbus \
--ram=$memory \
--vcpus=$vcpu \
--os-variant=linux \
--network bridge=$interface,model=$model \
--graphics $graphics \
--console pty,target_type=serial \
--import \
--noautoconsole
Comment ajouter un disque vide à la volée sur un domaine invité ?
Ce script demande trois paramètres :
•.$1 : le nom de l’invité
•.$2 : le nom du disques
•.$3 : la taille du disque en Go
https://raw.githubusercontent.com/goffinet/virt-scripts/master/add-storage.sh
#!/bin/bash
# Variables
guest=$1
disk=/var/lib/libvirt/images/${1}-${2}.img
size=$3
seek=$[${size}*1024]
# Create Spare Disk with dd
dd if=/dev/zero of=$disk bs=1M seek=$seek count=0
# Or create a qcow2 disk
#qemu-img create -f qcow2 -o preallocation=metadata $disk ${size}G
# Attach the disk on live guest with persistence
virsh attach-disk $guest $disk $2 --cache none --live --persistent
# Detach the disk
#virsh detach-disk $guest $disk --persistent --live
Note.
•.Manipulation de disques avec kpartx
Ajouter un pool pour stocker les disques des domaines
virsh pool-define-as Images dir - - - - /home/so/Documents/kvm/images
virsh pool-list --all
virsh pool-build Images
virsh pool-start Images
virsh pool-autostart Images
virsh pool-list
virsh pool-info Images
•.LVM2
•.iSCSI
Lister les réseaux virtuels disponibles :
Lister les adresses IP attribuées par un réseau virtuel :
virsh net-dhcp-leases default
Expiry Time MAC address Protocol IP address Hostname Client ID or DUID
-------------------------------------------------------------------------------------------------------------------
2017-02-16 16:52:03 52:54:00:15:35:f8 ipv4 192.168.122.129/24 arch ff:00:15:35:f8:00:01:00:01:20:33:48:d8:52:54:00:01:fb:0d
2017-02-16 16:52:15 52:54:00:3d:6c:39 ipv4 192.168.122.126/24 u1 -
2017-02-16 16:52:11 52:54:00:50:ac:4a ipv4 192.168.122.253/24 c1 -
2017-02-16 16:52:05 52:54:00:87:40:65 ipv4 192.168.122.130/24 d1 -
2017-02-16 16:52:09 52:54:00:91:31:a2 ipv4 192.168.122.212/24 k1 -
2017-02-16 16:52:20 52:54:00:b1:a7:a7 ipv4 192.168.122.173/24 m1 -
Obtenir la base d’une définition de réseau virtuel (ici default) dans un fichier lab.xml :
virsh net-dumpxml default > lab.xml
La commande uuidgen permet de générer un uuid :
Si on défini un nouveau réseau “lab” utilisant l’interface virbr1 pour laquelle le NAT est activé, voici à quoi se fichier devrait ressembler :
<network>
<name>lab</name>
<uuid>8293bf7a-ccf6-461b-8466-a058e7346d79</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr1' stp='on' delay='0'/>
<mac address='52:54:00:63:e8:10'/>
<ip address='192.168.22.254' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.22.100' end='192.168.22.150'/>
</dhcp>
</ip>
</network>
La balise forward mode peut prendre des valeurs comme nat, route, bridge, etc. En son absence le réseau est isolé.
Installation du nouveau réseau lab :
Démarrage du réseau :
Ensuite, faire en sorte qu’il démarre automatiquement :
Pour attacher un domaine existant au réseau lab, il faut créer un fichier qui reprend les paramètres d’une interface :
<interface type='bridge'>
<mac address='52:54:00:f7:e3:53'/>
<source bridge='virbr1'/>
<target dev='vnet0'/>
<model type='virtio'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
Pour mettre à jour l’attachement de la carte réseau :
virsh update-device vm-test virbr1.xml
On peut prendre une définition d’interface comme suit. Il s’agit de modifier balise “alias name” en mettant une nouvelle valeur net1 par exemple et en modifiant l’adresse MAC pour la rendre originale :
<interface type='bridge'>
<mac address='52:54:00:aa:bb:cc'/>
<source bridge='virbr1'/>
<target dev='vnet0'/>
<model type='virtio'/>
<alias name='net0'/>
</interface>
On peut alors attacher la carte au domaine en “live” :
virsh attach-device nom_de_domaine fichier.xml
Création d’un réseau isolé nommé “lan” sur l’interface “vrirbr3”
https://github.com/goffinet/virt-scripts/blob/master/add-isolated-bridge.sh
#!/bin/bash
# Create an isolated bridge
bridge="virbr3"
name=lan
path=/tmp
cat << EOF > $path/$name.xml
<network>
<name>$name</name>
<bridge name='$bridge' stp='on' delay='0'/>
</network>
EOF
virsh net-destroy $name
virsh net-create $path/$name.xml
#virsh net-autostart $name
Voir chapitre sur le routage et le pare-feu :
Le logiciel virt-builder permet de construire rapidement une VM à partir d’une image disponible sur le site de libguestfs. Il est paramétrable : voir https://libguestfs.org/virt-builder.1.html.
On citera aussi le projet OZ : https://github.com/clalancette/oz.
On peut tenter d’améliorer les scripts des exercices précédents et se poser quelques questions
•.Déploiement de template (https://www.greenhills.co.uk/2013/03/24/cloning-vms-with-kvm.html) ou machines fraîchement installées ?
•.Stockage capacité ?
•.Stockage type ? qcow2 ou raw
•.RAM minimum ?
•.Réseau ponté, NAT ?
•.adresse IP statique ou dhcp gérée ?
•.IPv6
•.partitionnement automatique / personnalisé LVM2
•.hostname
•.clé SSH
•.paquets nécessaires
•.commandes post install (service, hostname, fichiers, etc.)
Déploiement silencieux selon un profil de VM et d’installation.
Etude de cas :
•.déploiement et gestion de VPS
•.profils de VM (Centos 7)
•.small, medium, large
•.modèle à cloner : small + virt-sysprep + sparsify + virt-clone
•.profils d’installation
•.core + bootproto dhcp
•.docker-engine, httpd, mariadb, … + bootproto static
•.Déploiement de services
•.Traditionnel : scripts et fichier Kickstart
•.Ansible : playbooks (modules rpm, …)
•.Docker
•.Une combinaison
•.Surveillance / rapports
•.scripts
•.solutions commerciales / WebUI
Cet exercice est réalisé sous Centos 7.
Un serveur Web sur l’hyperviseur, httpd par exemple, ou situé ailleurs rend disponible deux dossiers dans /var/www/html :
•./var/www/html/repo : contient la copie d’un CD d’installation
•./var/www/html/conf : contient le script de création, les fichiers Kickstart générés et une clé publique SSH
Deux sources sont à définir :
•.Sources d’installation : HTTP ou local
•.Fichier Kickstart : HTTP ou local
Un script de création VM “small”
•.1 vCPU
•.1 Go RAM
•.16 Go qcow2
•.NIC : virb1 (192.168.22.0)
Configuration du système prédéfini dans un fichier Kickstart auquel correspond un profil d’installation Centos 7 avec un minimum de paquets, authentification à clé SSH et partionnement LVM2.
Il est nécessaire copier la clé publique de l’administrateur afin d’assurer
Pour les besoins de l’exercice, on désactivera le pare-feu.
•.NAT
•.192.168.22.254/24
•.DHCP .100-.150
•.virb1
#!/bin/bash
## usage : autovm.sh [type] [nom domaine]
## autovm.sh $1 $2
## types (appel d'un fichier kickstarts):
## core
## Variables
## 1. $type : Fichier Kickstart
type=$1
## 2. $name : Nom du domaine
name=$2
## 3. $vol : Emplacement des disques
vol=/var/lib/libvirt/images
## 4. $conf : Emplacement HTTP des fichiers Kickstart
conf=https://192.168.122.1/conf
## 5. $mirror : Sources d'installation HTTP
mirror=https://192.168.122.1/repo
## Miroirs publics
#mirror=https://centos.mirrors.ovh.net/ftp.centos.org/7/os/x86_64
#mirror=https://ftp.belnet.be/ftp.centos.org/7/os/x86_64
#mirror=https://mirror.i3d.net/pub/centos/7/os/x86_64
## 6. $temp : nom temporaire pour le fichier Kickstart
temp="$name-$(uuidgen | cut -d - -f 1)"
## 7. $www : emplacement physique des fichiers de configuration
www=/var/www/html/conf
gest_dom ()
{
## Gestion des noms utilisés, ici pour un lab (à améliorer)
## Arrêt et retrait de la VM
echo "Arrêt et retrait de la VM $name"
/bin/virsh destroy $name; /bin/virsh undefine $name --remove-all-storage
}
prep_ks ()
{
## Préparation du fichier Kickstart
echo "Préparation du fichier Kickstart"
cp $www/$type.ks $www/$temp.ks
chown apache:apache $www/$temp.ks
## Report du hostname
sed -i "s/network --hostname=.*/network --hostname=$name/g" $www/$temp.ks
##
}
virt_install ()
{
## Démarrage de l'installation du domaine
echo "Démarrage de l'installation du domaine $name"
## Installation et lancement silencieux en mode texte
## selon la baseline définie Centos 7 1GB/1vCPU/HD8GB/1NIC/ttyS0
nohup \
virt-install \
--virt-type kvm \
--name=$name \
--disk path=/var/lib/libvirt/images/$name.qcow2,size=8,format=qcow2 \
--ram=1024 \
--vcpus=1 \
--os-variant=rhel7 \
--network bridge=virbr0 \
--graphics none \
--noreboot \
--console pty,target_type=serial \
--location $mirror \
-x "ks=$conf/$temp.ks console=ttyS0,115200n8 serial" \
> /dev/null 2>&1 &
## choix installation cdrom avec Kickstart local
#ks=/var/www/html/conf
#iso=path/to/iso
#--cdrom $iso \
#--initrd-inject=/$temp.ks -x "ks=file:/$temp.ks console=ttyS0,115200n8 serial" \
}
gest_dom
prep_ks
virt_install
# rm -f $www/$temp.ks
## hostname
## bootproto dhcp ou static
##NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
## vda 252:0 0 8G 0 disk
## ├─vda1 252:1 0 500M 0 part /boot
## ├─vda2 252:2 0 6,7G 0 part (auto-grow)
## │ └─local0-root 253:0 0 3,9G 0 lvm /
## └─vda3 252:3 0 820M 0 part [SWAP] (auto-grow)
## install @core (minimum de paquets)
## post-install : update
## post-configuration ssh
install
keyboard --vckeymap=be-oss --xlayouts='be (oss)'
reboot
rootpw --plaintext testtest
timezone Europe/Brussels
url --url="https://192.168.122.1/repo"
lang fr_BE
firewall --disabled
network --bootproto=dhcp --device=eth0
network --hostname=template
# network --device=eth0 --bootproto=static --ip=192.168.22.10 --netmask 255.255.255.0 --gateway 192.168.22.254 --nameserver=192.168.22.11 --ipv6 auto
auth --useshadow --passalgo=sha512
text
firstboot --enable
skipx
ignoredisk --only-use=vda
bootloader --location=mbr --boot-drive=vda
zerombr
clearpart --all --initlabel
part /boot --fstype="xfs" --ondisk=vda --size=500
part swap --recommended
part pv.00 --fstype="lvmpv" --ondisk=vda --size=500 --grow
volgroup local0 --pesize=4096 pv.00
logvol / --fstype="xfs" --size=4000 --name=root --vgname=local0
%packages
@core
%end
%post
#yum -y update
mkdir /root/.ssh
curl https://192.168.122.1/conf/id_rsa.pub > /root/.ssh/authorized_keys
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
%end
Le projet a evolué en des scripts plus succints, notamment avec le script https://raw.githubusercontent.com/goffinet/virt-scripts/master/auto-install.sh :
#!/bin/bash
image=$1 # centos, debian, ubuntu
name=$2
fr_ubuntu_mirror=https://fr.archive.ubuntu.com/ubuntu/dists/xenial/main/installer-amd64/
fr_debian_mirror=https://ftp.debian.org/debian/dists/jessie/main/installer-amd64/
ovh_ubuntu_mirror=https://mirror.ovh.net/ubuntu/dists/xenial/main/installer-amd64/
ovh_debian_mirror=https://debian.mirrors.ovh.net/debian/dists/jessie/main/installer-amd64/
ovh_centos_mirror=https://centos.mirrors.ovh.net/ftp.centos.org/7/os/x86_64
belnet_ubuntu_mirror=https://ftp.belnet.be/ubuntu.com/ubuntu/dists/xenial/main/installer-amd64/
belnet_debian_mirror=https://ftp.belnet.be/debian/dists/jessie/main/installer-amd64/
belnet_centos_mirror=https://ftp.belnet.be/ftp.centos.org/7/os/x86_64
local_ubuntu_iso=/var/lib/iso/ubuntu-16.04.1-server-amd64.iso
url_ubuntu_iso=https://releases.ubuntu.com/16.04/ubuntu-16.04.1-server-amd64.iso
local_debian_iso=/var/lib/iso/debian-8.6.0-amd64-netinst.iso
url_debian_iso=https://cdimage.debian.org/debian-cd/8.6.0/amd64/iso-cd/debian-8.6.0-amd64-netinst.iso
local_centos_iso=/var/lib/iso/CentOS-7-x86_64-DVD-1611.iso
url_centos_iso=https://ftp.belnet.be/ftp.centos.org/7/isos/x86_64/CentOS-7-x86_64-DVD-1611.iso
ubuntu_mirror=$belnet_ubuntu_mirror
debian_mirror=$fr_debian_mirror
centos_mirror=$belnet_centos_mirror
check_apache () {
yum install -y httpd curl || apt-get install apache2 curl
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
systemctl enable httpd
systemctl start httpd
mkdir -p /var/www/html/conf
echo "this is ok" > /var/www/html/conf/ok
local check_value="this is ok"
local check_remote=$(curl -s https://127.0.0.1/conf/ok)
if [ "$check_remote"="$check_value" ] ; then
echo "Apache is working"
else
echo "Apache is not working"
exit
fi
}
ubuntu_install () {
local url=https://192.168.122.1/conf/ubuntu1604-preseed.cfg
local mirror=$ubuntu_mirror
touch /var/www/html/conf/ubuntu1604-preseed.cfg
cat << EOF > /var/www/html/conf/ubuntu1604-preseed.cfg
d-i debian-installer/language string en_US:en
d-i debian-installer/country string US
d-i debian-installer/locale string en_US
d-i debian-installer/splash boolean false
d-i localechooser/supported-locales multiselect en_US.UTF-8
d-i pkgsel/install-language-support boolean true
d-i console-setup/ask_detect boolean false
d-i keyboard-configuration/modelcode string pc105
d-i keyboard-configuration/layoutcode string be
d-i debconf/language string en_US:en
d-i netcfg/choose_interface select auto
d-i netcfg/dhcp_timeout string 5
d-i mirror/country string manual
d-i mirror/http/hostname string fr.archive.ubuntu.com
d-i mirror/http/directory string /ubuntu
d-i mirror/http/proxy string
d-i time/zone string Europe/Paris
d-i clock-setup/utc boolean true
d-i clock-setup/ntp boolean false
d-i passwd/root-login boolean false
d-i passwd/make-user boolean true
d-i passwd/user-fullname string user
d-i passwd/username string user
d-i passwd/user-password password testtest
d-i passwd/user-password-again password testtest
d-i user-setup/allow-password-weak boolean true
d-i passwd/user-default-groups string adm cdrom dialout lpadmin plugdev sambashare
d-i user-setup/encrypt-home boolean false
d-i apt-setup/restricted boolean true
d-i apt-setup/universe boolean true
d-i apt-setup/backports boolean true
d-i apt-setup/services-select multiselect security
d-i apt-setup/security_host string security.ubuntu.com
d-i apt-setup/security_path string /ubuntu
tasksel tasksel/first multiselect openssh-server
d-i pkgsel/include string openssh-server python-simplejson vim
d-i pkgsel/upgrade select safe-upgrade
d-i pkgsel/update-policy select none
d-i pkgsel/updatedb boolean true
d-i partman/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm_nooverwrite boolean true
d-i partman/confirm boolean true
d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-auto-lvm/no_boot boolean true
d-i partman-md/device_remove_md boolean true
d-i partman-md/confirm boolean true
d-i partman-md/confirm_nooverwrite boolean true
d-i partman-auto/method string lvm
d-i partman-auto-lvm/guided_size string max
d-i partman-partitioning/confirm_write_new_label boolean true
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
d-i finish-install/reboot_in_progress note
d-i finish-install/keep-consoles boolean false
d-i cdrom-detect/eject boolean true
d-i preseed/late_command in-target sed -i 's/PermitRootLogin\ prohibit-password/PermitRootLogin\ yes/' /etc/ssh/sshd_config ; in-target wget https://gist.githubusercontent.com/goffinet/f515fb4c87f510d74165780cec78d62c/raw/7cf2c788c1c5600f7433d16f8f352c877a281a6a/ubuntu-grub-console.sh ; in-target sh ubuntu-grub-console.sh
EOF
virt-install \
--virt-type kvm \
--name=$name \
--disk path=/var/lib/libvirt/images/$name.qcow2,size=8,format=qcow2 \
--ram=512 \
--vcpus=1 \
--os-variant=ubuntusaucy \
--network bridge=virbr0 \
--graphics none \
--console pty,target_type=serial \
--location $mirror \
-x "auto=true hostname=$name domain= url=$url text console=ttyS0,115200n8 serial"
}
debian_install () {
local url=https://192.168.122.1/conf/debian8-preseed.cfg
local mirror=$debian_mirror
touch /var/www/html/conf/debian8-preseed.cfg
cat << EOF > /var/www/html/conf/debian8-preseed.cfg
d-i debian-installer/locale string en_US
d-i keyboard-configuration/xkb-keymap select be
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string unassigned-hostname
d-i netcfg/get_domain string unassigned-domain
d-i netcfg/wireless_wep string
d-i mirror/country string manual
d-i mirror/http/hostname string ftp.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string
d-i passwd/make-user boolean false
d-i passwd/root-password password testtest
d-i passwd/root-password-again password testtest
d-i clock-setup/utc boolean true
d-i time/zone string Europe/Paris
d-i clock-setup/ntp boolean true
d-i partman-auto/method string lvm
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-md/device_remove_md boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-auto/choose_recipe select atomic
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman-md/confirm boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
tasksel tasksel/first multiselect standard
d-i pkgsel/include string openssh-server vim
d-i pkgsel/upgrade select full-upgrade
popularity-contest popularity-contest/participate boolean false
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
d-i grub-installer/bootdev string /dev/vda
d-i finish-install/keep-consoles boolean true
d-i finish-install/reboot_in_progress note
d-i preseed/late_command string in-target sed -i 's/PermitRootLogin\ without-password/PermitRootLogin\ yes/' /etc/ssh/sshd_config; in-target wget https://gist.githubusercontent.com/goffinet/f515fb4c87f510d74165780cec78d62c/raw/7cf2c788c1c5600f7433d16f8f352c877a281a6a/ubuntu-grub-console.sh ; in-target sh ubuntu-grub-console.sh
EOF
virt-install \
--virt-type kvm \
--name=$name \
--disk path=/var/lib/libvirt/images/$name.qcow2,size=8,format=qcow2 \
--ram=512 \
--vcpus=1 \
--os-variant=debianwheezy \
--network bridge=virbr0 \
--graphics none \
--console pty,target_type=serial \
--location $mirror \
-x "auto=true hostname=$name domain= url=$url text console=ttyS0,115200n8 serial"
}
centos_install () {
local url=https://192.168.122.1/conf/centos7.ks
local mirror=$centos_mirror
read -r -d '' packages <<- EOM
@core
wget
EOM
touch /var/www/html/conf/centos7.ks
cat << EOF > /var/www/html/conf/centos7.ks
install
reboot
rootpw --plaintext testtest
keyboard --vckeymap=be-oss --xlayouts='be (oss)'
timezone Europe/Paris --isUtc
#timezone Europe/Brussels
lang en_US.UTF-8
#lang fr_BE
#cdrom
url --url="$mirror"
firewall --disabled
network --bootproto=dhcp --device=eth0
network --bootproto=dhcp --device=eth1
network --hostname=$name
# network --device=eth0 --bootproto=static --ip=192.168.22.10 --netmask 255.255.255.0 --gateway $bridgeip4 --nameserver=$bridgeip4 --ipv6 auto
#auth --useshadow --passalgo=sha512
text
firstboot --enable
skipx
ignoredisk --only-use=vda
bootloader --location=mbr --boot-drive=vda
zerombr
clearpart --all --initlabel
#autopart --type=thinp # See the bug resolved in 7.3 https://bugzilla.redhat.com/show_bug.cgi?id=1290755
autopart --type=lvm
#part /boot --fstype="xfs" --ondisk=vda --size=500
#part swap --recommended
#part pv.00 --fstype="lvmpv" --ondisk=vda --size=500 --grow
#volgroup local0 --pesize=4096 pv.00
#logvol / --fstype="xfs" --size=4000 --name=root --vgname=local0
%packages
$packages
%end
%post
yum -y update && yum -y upgrade
#mkdir /root/.ssh
#curl ${conf}/id_rsa.pub > /root/.ssh/authorized_keys
#sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
%end
EOF
virt-install \
--virt-type=kvm \
--name=$name \
--disk path=/var/lib/libvirt/images/$name.qcow2,size=8,format=qcow2 \
--ram=2048 \
--vcpus=1 \
--os-variant=rhel7 \
--network bridge=virbr0 \
--graphics none \
--noreboot \
--console pty,target_type=serial \
--location $mirror \
-x "auto=true hostname=$name domain= ks=$url text console=ttyS0,115200n8 serial"
}
start_install () {
if [ $image = centos ] ; then
centos_install
elif [ $image = debian ] ; then
debian_install
elif [ $image = ubuntu ] ; then
ubuntu_install
else
echo "Erreur dans le script : ./auto-install.sh [ centos | debian | ubuntu ] nom_de_vm"
exit
fi
}
check_apache
start_install
Seul pré-requis : Sytème Linux (Centos 7) avec un accès ssh avec authentification avec clé et Python installé.
Une résolution de nom robuste est conseillée.
•.Inventaire (fichier hosts)
•.Modules
•.Playbooks
yum install ansible
echo "nameserver 192.168.122.1" >> /etc/resolv.conf
mv /etc/ansible/hosts /etc/ansible/hosts.old
echo -e "[lab]\nvm0[1:4]" > /etc/ansible/hosts
cat /etc/ansible/hosts
ansible all -m ping
ansible vm01 -m ping
ansible all -m setup
ansible lab -m yum -a "name=openssh-server state=present"
Dans cette seconde procédure, on pourra choisir le profil de la machine virtuelle à partir d’un seul script.
Ce script vise à créer une machine virtuelle KVM d’une certaine capacité (small, medium, large) de manière automatique.
L’installation est minimale mais suffisante (core) pour assurer la gestion par Ansible et déployer des containers en tant que services.
On peut l’améliorer dans le profilage des installations (pré-installation, services, fichiers de configuration mais aussi dans la maintenance de la machine virtuelle (fin de l’installation, suppression du fichier Kickstart, –> via boucle while/surveillance du processus lancé, génération de rapports, logs) ou encore la gestion des erreurs.
Une option “gold image” ou modèle qui permettrait de préparer une VM et de cloner une telle installation fraîche serait un must, car elle répondrait à autre approche d’une solution de déploiement automatique de machines virtuelles.
Pour comprendre ce script, on le lira en trois temps :
1.variables générales au début
•.et leur corps principal (tout à la fin)
•.qui appelle trois fonctions :
•.gest_dom : qui efface le domaine invoqué (niveau de sévérité : lab)
•.prep_ks : qui prépare le fichier d’installation Kickstart
•.virt_install : qui crée la machine, la lance et démarre l’installation automatique.
#/bin/bash
# fichier autovm.sh
## usage : autovm.sh [type] [nom domaine]
## autovm.sh $1 $2
## Création et installation automatisée Fedora/Centos 7
## types (profils, baselines):
## small, medium ou large
##
## Variables générales
## 1. $name : Nom du domaine
name=$2
## 2. $type : type d'installation
type=$1
## 3. $vol : Emplacement des disques
vol=/var/lib/libvirt/images
## 4. $conf : Emplacement HTTP des fichiers Kickstart
## Serveur Web sur l'hyperviseur (adresse du réseau "Default")
conf=https://192.168.122.1/conf
## 5. $mirror : Sources d'installation HTTP
mirror=https://192.168.122.1/repo
## Miroirs publics
#mirror=https://centos.mirrors.ovh.net/ftp.centos.org/7/os/x86_64
#mirror=https://ftp.belnet.be/ftp.centos.org/7/os/x86_64
#mirror=https://mirror.i3d.net/pub/centos/7/os/x86_64
## 6. $temp : nom temporaire pour le fichier Kickstart
temp="$name-$(uuidgen | cut -d - -f 1)"
## 7. $www : emplacement physique des fichiers de configuration
www=/var/www/html/conf
gest_dom ()
{
## Gestion des noms utilisés, ici pour un lab (à améliorer)
## Arrêt et retrait de la VM
echo "Arrêt et retrait de la VM $name"
/bin/virsh destroy $name; /bin/virsh undefine $name
#Erase the VM disk
rm -f $vol/$name.*
}
prep_ks ()
{
## Préparation du fichier Kickstart
echo "Préparation du fichier Kickstart"
##
touch $www/$temp.ks
cat << EOF > $www/$temp.ks
install
keyboard --vckeymap=be-oss --xlayouts='be (oss)'
reboot
rootpw --plaintext testtest
timezone Europe/Brussels
url --url="$mirror"
lang fr_BE
firewall --disabled
network --bootproto=dhcp --device=eth0
network --hostname=$name
# network --device=eth0 --bootproto=static --ip=192.168.22.10 --netmask 255.255.255.0 --gateway 192.168.22.254 --nameserver=192.168.22.11 --ipv6 auto
auth --useshadow --passalgo=sha512
text
firstboot --enable
skipx
ignoredisk --only-use=vda
bootloader --location=mbr --boot-drive=vda
zerombr
clearpart --all --initlabel
part /boot --fstype="xfs" --ondisk=vda --size=500
part swap --recommended
part pv.00 --fstype="lvmpv" --ondisk=vda --size=500 --grow
volgroup local0 --pesize=4096 pv.00
logvol / --fstype="xfs" --size=4000 --name=root --vgname=local0
%packages
@core
%end
%post
#yum -y update
mkdir /root/.ssh
curl $conf/id_rsa.pub > /root/.ssh/authorized_keys
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
%end
EOF
chown apache:apache $www/$temp.ks
}
virt_install ()
{
installation ()
{
## Démarrage de l'installation du domaine
echo "Démarrage de l'installation du domaine $name"
## Installation et lancement silencieux en mode texte
## selon le profil (baseline) défini dans la variable $type
nohup \
/bin/virt-install \
--virt-type kvm \
--name=$name \
--disk path=$vol/$name.$format,size=$size,format=$format \
--ram=$ram \
--vcpus=$vcpus \
--os-variant=rhel7 \
--network bridge=$bridge \
--graphics none \
--noreboot \
--console pty,target_type=serial \
--location $mirror \
-x "ks=$conf/$temp.ks console=ttyS0,115200n8 serial" \
> /dev/null 2>&1 &
## choix installation cdrom avec Kickstart local
#ks=/var/www/html/conf
#iso=path/to/iso
#--cdrom $iso \
#--initrd-inject=/$temp.ks -x "ks=file:/$temp.ks console=ttyS0,115200n8 serial" \
}
if [ $type = small ] ; then
size=8
format=qcow2
ram=1024
vcpus=1
bridge=virbr0
installation
elif [ $type = medium ] ; then
size=16
format=qcow2
ram=2048
vcpus=2
bridge=virbr0
installation
elif [ $type = large ] ; then
size=32
format=qcow2
ram=4096
vcpus=4
bridge=virbr0
installation
else
exit
fi
}
gest_dom
prep_ks
virt_install
# rm -f $www/$temp.ks
…
virsh # version
Compiled against library: libvirt 2.0.0
Using library: libvirt 2.0.0
Utilisation de l'API : QEMU 2.0.0
Exécution de l'hyperviseur : QEMU 1.5.3
•.attach-device attacher un périphérique depuis un fichier XML
•.attach-disk attacher un périphérique disque
•.attach-interface attacher une interface réseau
•.autostart démarrer automatiquement un domaine
•.blkdeviotune Set or query a block device I/O tuning parameters.
•.blkiotune Get or set blkio parameters
•.blockcommit Start a block commit operation.
•.blockcopy Start a block copy operation.
•.blockjob Manage active block operations
•.blockpull Populate a disk from its backing image.
•.blockresize Modifie la taille d’un périphérique bloc de domaine.
•.change-media Change media of CD or floppy drive
•.console se connecter à la console invitée
•.cpu-baseline compute baseline CPU
•.cpu-compare compare host CPU with a CPU described by an XML file
•.cpu-stats show domain cpu statistics
•.create créer un domaine depuis un fichier XML
•.define définir (mais ne pas démarrer) un domaine depuis un fichier XML
•.desc show or set domain’s description or title
•.destroy destroy (stop) a domain
•.detach-device détacher un périphérique depuis un fichier XML
•.detach-disk détacher un périphérique disque
•.detach-interface détacher une interface réseau
•.domdisplay domain display connection URI
•.domfsfreeze Freeze domain’s mounted filesystems.
•.domfsthaw Thaw domain’s mounted filesystems.
•.domfsinfo Get information of domain’s mounted filesystems.
•.domfstrim Invoke fstrim on domain’s mounted filesystems.
•.domhostname print the domain’s hostname
•.domid convertir un nom de domaine ou UUID en ID de domaine
•.domif-setlink set link state of a virtual interface
•.domiftune get/set parameters of a virtual interface
•.domjobabort abort active domain job
•.domjobinfo domain job information
•.domname convertir l’ID ou l’UUID du domaine en nom de domaine
•.domrename rename a domain
•.dompmsuspend suspend a domain gracefully using power management functions
•.dompmwakeup wakeup a domain from pmsuspended state
•.domuuid convertir un ID ou un nom de domaine en UUID de domaine
•.domxml-from-native Convert native config to domain XML
•.domxml-to-native Convert domain XML to native config
•.dump vider l’espace mémoire d’un domaine dans un fichier pour analyse
•.dumpxml informations du domaine en XML
•.edit edit XML configuration for a domain
•.event Domain Events
•.inject-nmi Inject NMI to the guest
•.iothreadinfo view domain IOThreads
•.iothreadpin control domain IOThread affinity
•.iothreadadd add an IOThread to the guest domain
•.iothreaddel delete an IOThread from the guest domain
•.send-key Send keycodes to the guest
•.send-process-signal Send signals to processes
•.lxc-enter-namespace LXC Guest Enter Namespace
•.managedsave managed save of a domain state
•.managedsave-remove Remove managed save of a domain
•.memtune Get or set memory parameters
•.perf Get or set perf event
•.metadata show or set domain’s custom XML metadata
•.migrate migrer un domaine vers un autre hôte
•.migrate-setmaxdowntime set maximum tolerable downtime
•.migrate-compcache get/set compression cache size
•.migrate-setspeed Set the maximum migration bandwidth
•.migrate-getspeed Get the maximum migration bandwidth
•.migrate-postcopy Switch running migration from pre-copy to post-copy
•.numatune Get or set numa parameters
•.qemu-attach QEMU Attach
•.qemu-monitor-command QEMU Monitor Command
•.qemu-monitor-event QEMU Monitor Events
•.qemu-agent-command QEMU Guest Agent Command
•.reboot redémarrer un domaine
•.reset reset a domain
•.restore restaurer un domaine à partir d’un état sauvé dans un fichier
•.resume réactiver un domaine
•.save enregistrer l’état du domaine dans un fichier
•.save-image-define redefine the XML for a domain’s saved state file
•.save-image-dumpxml saved state domain information in XML
•.save-image-edit edit XML for a domain’s saved state file
•.schedinfo montrer/définir les paramètres du planificateur
•.screenshot take a screenshot of a current domain console and store it into a file
•.set-user-password set the user password inside the domain
•.setmaxmem changer la limite maximum de mémoire
•.setmem changer la mémoire allouée
•.setvcpus changer le nombre de processeurs virtuels
•.shutdown arrêter un domaine proprement
•.start démarrer un domaine (précédemment défini)
•.suspend suspendre un domaine
•.ttyconsole console TTY
•.undefine undefine a domain
•.update-device update device from an XML file
•.vcpucount domain vcpu counts
•.vcpuinfo detailed domain vcpu information
•.vcpupin control or query domain vcpu affinity
•.emulatorpin control or query domain emulator affinity
•.vncdisplay affichage vnc
•.guestvcpus query or modify state of vcpu in the guest (via agent)
•.domblkerror Show errors on block devices
•.domblkinfo domain block device size information
•.domblklist list all domain blocks
•.domblkstat retourner les statistiques d’un périphérique en mode bloc pour un domaine
•.domcontrol domain control interface state
•.domif-getlink get link state of a virtual interface
•.domifaddr Get network interfaces’ addresses for a running domain
•.domiflist list all domain virtual interfaces
•.domifstat obtenir les statistiques d’une interface réseau pour un domaine
•.dominfo informations du domaine
•.dommemstat get memory statistics for a domain
•.domstate état du domaine
•.domstats get statistics about one or multiple domains
•.domtime domain time
•.list lister les domaines
•.allocpages Manipulate pages pool size
•.capabilities capacités
•.cpu-models CPU models
•.domcapabilities domain capabilities
•.freecell Mémoire NUMA disponible
•.freepages NUMA free pages
•.hostname afficher le nom d’hôte de l’hyperviseur
•.maxvcpus connection vcpu maximum
•.node-memory-tune Get or set node memory parameters
•.nodecpumap node cpu map
•.nodecpustats Prints cpu stats of the node.
•.nodeinfo informations du noeud
•.nodememstats Prints memory stats of the node.
•.nodesuspend suspend the host node for a given time duration
•.sysinfo print the hypervisor sysinfo
•.uri afficher l’URI canonique de l’hyperviseur
•.version afficher la version
•.iface-begin create a snapshot of current interfaces settings, which can be later committed (iface-commit) or restored (iface-rollback)
•.iface-bridge create a bridge device and attach an existing network device to it
•.iface-commit commit changes made since iface-begin and free restore point
•.iface-define define an inactive persistent physical host interface or modify an existing persistent one from an XML file
•.iface-destroy destroy a physical host interface (disable it / “if-down”)
•.iface-dumpxml interface information in XML
•.iface-edit edit XML configuration for a physical host interface
•.iface-list list physical host interfaces
•.iface-mac convert an interface name to interface MAC address
•.iface-name convert an interface MAC address to interface name
•.iface-rollback rollback to previous saved configuration created via iface-begin
•.iface-start start a physical host interface (enable it / “if-up”)
•.iface-unbridge undefine a bridge device after detaching its slave device
•.iface-undefine undefine a physical host interface (remove it from configuration)
•.nwfilter-define define or update a network filter from an XML file
•.nwfilter-dumpxml network filter information in XML
•.nwfilter-edit edit XML configuration for a network filter
•.nwfilter-list list network filters
•.nwfilter-undefine undefine a network filter
•.net-autostart démarrer automatiquement un réseau
•.net-create créer un réseau depuis un fichier XML
•.net-define define an inactive persistent virtual network or modify an existing persistent one from an XML file
•.net-destroy destroy (stop) a network
•.net-dhcp-leases print lease info for a given network
•.net-dumpxml informations du réseau en XML
•.net-edit edit XML configuration for a network
•.net-event Network Events
•.net-info network information
•.net-list lister les réseaux
•.net-name convertir l’UUID d’un réseau en nom de réseau
•.net-start démarrer un réseau inactif (précédemment défini)
•.net-undefine undefine a persistent network
•.net-update update parts of an existing network’s configuration
•.net-uuid convertir le nom d’un réseau en UUID de réseau
•.nodedev-create create a device defined by an XML file on the node
•.nodedev-destroy destroy (stop) a device on the node
•.nodedev-detach detach node device from its device driver
•.nodedev-dumpxml node device details in XML
•.nodedev-list enumerate devices on this host
•.nodedev-reattach reattach node device to its device driver
•.nodedev-reset reset node device
•.secret-define define or modify a secret from an XML file
•.secret-dumpxml secret attributes in XML
•.secret-get-value Output a secret value
•.secret-list list secrets
•.secret-set-value set a secret value
•.secret-undefine undefine a secret
•.snapshot-create Create a snapshot from XML
•.snapshot-create-as Create a snapshot from a set of args
•.snapshot-current Get or set the current snapshot
•.snapshot-delete Delete a domain snapshot
•.snapshot-dumpxml Dump XML for a domain snapshot
•.snapshot-edit edit XML for a snapshot
•.snapshot-info snapshot information
•.snapshot-list List snapshots for a domain
•.snapshot-parent Get the name of the parent of a snapshot
•.snapshot-revert Revert a domain to a snapshot
•.find-storage-pool-sources-as find potential storage pool sources
•.find-storage-pool-sources discover potential storage pool sources
•.pool-autostart démarrer automatiquement un pool
•.pool-build construire un pool
•.pool-create-as créer un pool depuis un ensemble d’arguments
•.pool-create créer un pool depuis un fichier XML
•.pool-define-as définir un pool à partir d’un ensemble d’argument
•.pool-define define an inactive persistent storage pool or modify an existing persistent one from an XML file
•.pool-delete effacer un pool
•.pool-destroy destroy (stop) a pool
•.pool-dumpxml informations du pool en XML
•.pool-edit edit XML configuration for a storage pool
•.pool-info informations du pool de stockage
•.pool-list lister les pools
•.pool-name convertir l’UUID d’un pool en nom de pool
•.pool-refresh rafraichir un pool
•.pool-start démarrer un pool inactif (précédemment défini)
•.pool-undefine supprimer un pool inactif
•.pool-uuid convertir le nom d’un pool en UUID de pool
•.pool-event Storage Pool Events
•.vol-clone cloner un volume.
•.vol-create-as créer un volume depuis un ensemble d’arguments
•.vol-create créer un volume depuis un fichier XML
•.vol-create-from create a vol, using another volume as input
•.vol-delete supprimer un volume
•.vol-download download volume contents to a file
•.vol-dumpxml informations du volume en XML
•.vol-info informations du volume de stockage
•.vol-key renvoie la clé du volume pour un nom ou un chemin donné de volume
•.vol-list lister les volumes
•.vol-name returns the volume name for a given volume key or path
•.vol-path renvoie le chemin vers le volume pour un nom ou une clé donnée de volume
•.vol-pool renvoie le pool de stockage pour un nom ou un chemin donné de volume
•.vol-resize modifier la taille d’un volume
•.vol-upload upload file contents to a volume
•.vol-wipe wipe a vol
•.cd change the current directory
•.echo echo arguments
•.exit quitter ce terminal interactif
•.help imprimer l’aide
•.pwd print the current directory
•.quit quitter ce terminal interactif
•.connect (re)connecter à l’hyperviseur